/*
 *  stack.c
 *
 *  Created on: 2010-5-12
 *      Author: liuyond
 *    Abstract: this file will implement the simulation of the following instruction
 *				PUSH, POP, PUSHF, POPF
 */
#include "cpu.h"

void PUSH_ES(cpu_t *cpu, instruction_t *i)
{
	cpu_push_mem_word(cpu, cpu_get_seg(cpu, ES));
}

void POP_ES(cpu_t *cpu, instruction_t *i)
{
	cpu_set_seg(cpu, ES, cpu_pop_mem_word(cpu));
}

void PUSH_CS(cpu_t *cpu, instruction_t *i)
{
	cpu_push_mem_word(cpu, cpu_get_seg(cpu, CS));
}

void PUSH_SS(cpu_t *cpu, instruction_t *i)
{
	cpu_push_mem_word(cpu, cpu_get_seg(cpu, SS));
}

void POP_SS(cpu_t *cpu, instruction_t *i)
{
	cpu_set_seg(cpu, SS, cpu_pop_mem_word(cpu));
}

void PUSH_DS(cpu_t *cpu, instruction_t *i)
{
	cpu_push_mem_word(cpu, cpu_get_seg(cpu, DS));
}

void POP_DS(cpu_t *cpu, instruction_t *i)
{
	cpu_set_seg(cpu, DS, cpu_pop_mem_word(cpu));
}

void PUSH_RX(cpu_t *cpu, instruction_t *i)
{
	int index = i->opcode & 0x7;
	cpu_push_mem_word(cpu, cpu_get_reg(cpu, index));
}

void POP_RX(cpu_t *cpu, instruction_t *i)
{
	int index = i->opcode & 0x7;
	int value = cpu_pop_mem_word(cpu);
	cpu_set_reg(cpu, index, value);
}

void PUSH_Ev(cpu_t *cpu, instruction_t *i)
{
	int tmp;

	if (i->operand.mod == 0x3)
	{
		// register operand
		tmp = cpu_get_reg(cpu, i->operand.rm);
	}
	else
	{
		// memory operand
		tmp = cpu_get_mem_word(cpu, i->operand.seg, i->operand.address);
	}
	cpu_push_mem_word(cpu, tmp);
}

void POP_Ev(cpu_t *cpu, instruction_t *i)
{
	int tmp = cpu_pop_mem_word(cpu);

	if (i->operand.mod == 0x3)
	{
		// register operand
		cpu_set_reg(cpu, i->operand.rm, tmp);
	}
	else
	{
		// memory operand
		cpu_set_mem_word(cpu, i->operand.seg, i->operand.address, tmp);
	}
}

void PUSHF(cpu_t *cpu, instruction_t *i)
{
	cpu_push_mem_word(cpu, cpu->flags);
}

void POPF(cpu_t *cpu, instruction_t *i)
{
	cpu->flags = cpu_pop_mem_word(cpu);
}

